
# -------------------------------------------------------------------------------
  "Main Functions of the Model"
# -------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Utility Function
#------------------------------------------------------------------------------
function u_fun(ce::CE_Economy_M, cc::Float64)
utility = (cc.^(1.0-ce.γ))/(1.0-ce.γ)
return utility
end
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Exogenous probability of message m=L, given π
#------------------------------------------------------------------------------
function f(ce::CE_Economy_M, π::Float64)
    Prob_mL  = cdf( Normal(0,1), (ce.α-π)./ce.σ_π );
return Prob_mL
end
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
#Posterior Function after observing d={0,1}  [before message m is realized]
#------------------------------------------------------------------------------
function F0_fun(ce::CE_Economy_M, ζ::Float64, d::Int64, DI::Float64, DP::Float64)
    #  d  = Observed default decisions
    #  DI = Prob(d=1|Type=I); lenders' conjecture
    #  DP = Prob(d=1|Type=P); lenders' conjecture
    ζtilde  = ζ;
    if d==1
    ζtilde  = ζ * DP / (ζ * DP  +(1-ζ)* DI)
    elseif d==0
    ζtilde  = ζ * (1-DP) / (ζ * (1-DP)  +(1-ζ)* (1-DI))
    end
    if isnan(ζtilde)
    ζtilde = 0.0
    end
    ζtilde = min( max(ζtilde,ce.z_grid[1]), ce.z_grid[end])
return  ζtilde
end
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Posterior Function after message m is realized
#------------------------------------------------------------------------------
function F_fun(ce::CE_Economy_M, Π::Float64, m::Int64, ζtilde::Float64)
    #Set m=1 for m=L. Set m=2 for m=NL
    #ζtilde is the posterior after observing default d={0,1}
    #Output: ζ_hat (does not include the Markov transition)
         ζ_hat  = ζtilde;
   if m==1  #m=L
         ζ_hat  = ζtilde * f(ce,0.)     / (ζtilde * f(ce,0.)      + (1-ζtilde)* f(ce,Π)     )
   elseif m==2  #m=NL
         ζ_hat  = ζtilde * (1-f(ce,0.)) / (ζtilde * (1-f(ce,0.))  + (1-ζtilde)* (1-f(ce,Π)) )
   end
       if isnan(ζ_hat)
       ζ_hat = 0.0
       end
return ζ_hat
end
#------------------------------------------------------------------------------
   
#----------------------------------------------------------------------------------
#Markov Transition Fx
#----------------------------------------------------------------------------------
function Markov_Switch_fx(ce::CE_Economy_M, z_hat::Float64)
   zprime = z_hat * ce.ΠT[1,1] + (1.0-z_hat) * ce.ΠT[2,1];
   return zprime
end
#----------------------------------------------------------------------------------


#------------------------------------------------------------------------------
# Value function in case of repayment
#------------------------------------------------------------------------------
function fun_bp(ce::CE_Economy_M, bp_v::Float64, π::Float64, b_v::Float64, y_v::Float64, B_v::Float64, q::Float64, Expec::Float64)  #Expec is the expected continuation value function (W)
    c_v = max(y_v - b_v* ((1-ce.mb)*ce.zb + ce.mb) - B_v*(1+π) + q*(bp_v-(1-ce.mb)*b_v), 1e-14)
    V_v = -u_fun(ce, c_v) - ce.β*Expec
return V_v
end
#------------------------------------------------------------------------------


#----------------------------------------------------------------------------------
#Repayment for an IIB
#----------------------------------------------------------------------------------
function Repayment_fx_IIB(ce::CE_Economy_M, Π_exp::Float64, qp::Float64)
Repayment_IIB = (1-ce.mb)* ( ce.zb*(1.0+Π_exp)  + qp )   + ce.mb*(1.0+Π_exp);
return Repayment_IIB
end
#----------------------------------------------------------------------------------

#----------------------------------------------------------------------------------
#Seconday Market price
#----------------------------------------------------------------------------------
function qB_fx(ce::CE_Economy_M, Π::Float64, ζ_hat::Float64, q::Float64; IIB=0)
    qB, qB_C,qB_S =[],[],[];
    if IIB ==0
        qB  = ce.mb + (1-ce.mb)*(ce.zb + q );
        qB_C, qB_S = qB, qB
    elseif IIB==1
        qB_C  =  Repayment_fx_IIB(ce, 0., q);
        qB_S  =  Repayment_fx_IIB(ce, Π,  q);
        qB    =  ζ_hat * qB_C  + (1-ζ_hat)*qB_S
    end
    return qB,qB_C,qB_S
end
#----------------------------------------------------------------------------------


#------------------------------------------------------------------------------
# Functions for Yields [quarterly] & Spreads [annualized]
#------------------------------------------------------------------------------
function Yield_fx(ce::CE_Economy_M,Price::Float64)    # Quarterly Yield (not annualized)
yield   = 1./Price .* (ce.mb + (1-ce.mb)*ce.zb) - ce.mb
return yield
end
function Spreads_fx(ce::CE_Economy_M,Price::Float64)   # Annualized Spreads
yield   = Yield_fx(ce,Price)
spread  = ( (1+yield)./(1+ce.r) ).^4   -1
spread  = spread*100
return spread
end
function Spreads_fx_matrix(ce::CE_Economy_M,Price::Array{Float64}) #Annualized Spreads (for sims)
yield   = 1./Price .* (ce.mb + (1-ce.mb)*ce.zb) - ce.mb
spread  = ( (1+yield)./(1+ce.r) ).^4   -1
spread  = spread*100
return spread
end
#------------------------------------------------------------------------------


#----------------------------------------------------------------------------------
function tauchen_fun(ny::Int64, ρ::Float64, σe::Float64; m=3, mu=0.0)
#----------------------------------------------------------------------------------
    σy = σe/sqrt((1-ρ^2))
    λ1 = -m*σy; λn = m*σy
    λgrid = linspace(λ1,λn,ny)
    ww = λgrid[2] - λgrid[1]
    distrib = Normal(0,1)
    Π = Array{Float64}(ny,ny)
    for ii=1:ny
        Π[ii,1] = cdf(distrib,(λ1+ww/2-(1-ρ)*mu-ρ*λgrid[ii])/σe)
        Π[ii,end] = 1.0-cdf(distrib,(λn-ww/2-(1-ρ)*mu-ρ*λgrid[ii])/σe)
        for jj=2:ny-1
            Π[ii,jj] = cdf(distrib,(λgrid[jj]+ww/2-(1-ρ)*mu-ρ*λgrid[ii])/σe) - cdf(distrib,(λgrid[jj]-ww/2-(1-ρ)*mu-ρ*λgrid[ii])/σe)
        end
    end
    return λgrid,Π
end
#----------------------------------------------------------------------------------